package chart;

import db.entity.PadLife;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JOptionPane;

import db.entity.PadLife;
import db.entity.WCSDataInterface;

import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.labels.CustomXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import util.Constants;

public class TendChartPanel extends ChartPanel{

	public static final int GRAPH_TTV = 0;
	public static final int GRAPH_STIR = 1;
	public static final int GRAPH_TIR = 2;
	public static final int GRAPH_TAPERSPC = 3;
	public static final int GRAPH_REMOVAL = 4;
	
	private static final long serialVersionUID = 1L;
	
	private TimeSeries averageSeries = null;
	private TimeSeries stdDevSeries = null;
	private TimeSeries newPadSeries = null;
	
	private TimeSeriesCollection averageDataset = null;
	private TimeSeriesCollection stdDevDataset = null;
	private TimeSeriesCollection newPadDataset = null;
	
	private NumberAxis averageAxis = null;
	private NumberAxis stdDevAxis = null;
	private NumberAxis newPadAxis = null;
	private DateAxis dateAxis = null;
	
	private ArrayList<String> avgToolTipArray = null;
	private ArrayList<String> sdvToolTipArray = null;
	private ArrayList<String> padToolTipArray = null;
	
	private XYPlot tendChartPlot = null;
	private JFreeChart tendChart = null;
	
	public TendChartPanel() 
	{
		super(null);
		initSeries();
		initAxis();
		initToolTip();
		renderPlot();
		tendChart = new JFreeChart("Tend Chart", JFreeChart.DEFAULT_TITLE_FONT, tendChartPlot, true);
		this.setChart(tendChart);
		this.setDisplayToolTips(true);
	}
	
	private void initSeries()
	{
		averageSeries = new TimeSeries("Average");
		averageDataset = new TimeSeriesCollection();
		averageDataset.addSeries(averageSeries);
		
		stdDevSeries = new TimeSeries("Standard Deviation");
		stdDevDataset = new TimeSeriesCollection();
		stdDevDataset.addSeries(stdDevSeries);
		
		newPadSeries = new TimeSeries("New Pad");
		newPadDataset = new TimeSeriesCollection();
		newPadDataset.addSeries(newPadSeries);
	}
	
	private void initAxis()
	{
		averageAxis = new NumberAxis("Average");
		averageAxis.setLabelPaint(Color.red);
		averageAxis.setNumberFormatOverride(Constants.GRAPH_DF);
		averageAxis.setAutoRangeIncludesZero(false);

		stdDevAxis = new NumberAxis("Standard Deviation");
		stdDevAxis.setLabelPaint(Color.blue);
		stdDevAxis.setNumberFormatOverride(Constants.GRAPH_DF);
		stdDevAxis.setAutoRangeIncludesZero(false);
		
		newPadAxis = new NumberAxis("New Pad");
		newPadAxis.setLabelPaint(Color.magenta);
		newPadAxis.setNumberFormatOverride(Constants.GRAPH_DF);
		newPadAxis.setAutoRangeIncludesZero(false);
		
		dateAxis = new DateAxis();
		dateAxis.setDateFormatOverride(new SimpleDateFormat("dd,MMM,yyyy(hh:mm:ssa)"));
	}
	
	private void initToolTip()
	{
		avgToolTipArray = new ArrayList<String>();
		sdvToolTipArray = new ArrayList<String>();
		padToolTipArray = new ArrayList<String>();
	}
	
	private void renderPlot()
	{
		tendChartPlot = new XYPlot();
		
		//Average
		XYLineAndShapeRenderer avgRenderer = new XYLineAndShapeRenderer();
		avgRenderer.setBaseShape(new Rectangle2D.Float(-2.0F, -2.0F, 4.0F, 4.0F));
		avgRenderer.setBasePaint(Color.red);
		avgRenderer.setUseFillPaint(true);
		avgRenderer.setBaseFillPaint(Color.LIGHT_GRAY);
		avgRenderer.setBaseShapesVisible(true);
		avgRenderer.setBaseShapesFilled(true);
		CustomXYToolTipGenerator avgToolTipGenerator = new CustomXYToolTipGenerator();
		avgToolTipGenerator.addToolTipSeries(this.avgToolTipArray);
		avgRenderer.setBaseToolTipGenerator(avgToolTipGenerator);
				
		tendChartPlot.setRangeAxis(0, averageAxis);
		tendChartPlot.setRangeAxisLocation(0, AxisLocation.BOTTOM_OR_LEFT);
		tendChartPlot.setDataset(0, averageDataset);
		tendChartPlot.mapDatasetToRangeAxis(0, 0);
		tendChartPlot.setRenderer(0, avgRenderer);
		
		//Standard Deviation
		XYLineAndShapeRenderer stdDevRenderer = new XYLineAndShapeRenderer();
		stdDevRenderer.setBaseShape(new Rectangle2D.Float(-2.0F, -2.0F, 4.0F, 4.0F));
		stdDevRenderer.setBasePaint(Color.blue);
		stdDevRenderer.setUseFillPaint(true);
		stdDevRenderer.setBaseFillPaint(Color.LIGHT_GRAY);
		stdDevRenderer.setBaseShapesVisible(true);
		stdDevRenderer.setBaseShapesFilled(true);
		CustomXYToolTipGenerator stdDevToolTipGenerator = new CustomXYToolTipGenerator();
		stdDevToolTipGenerator.addToolTipSeries(this.sdvToolTipArray);
		stdDevRenderer.setBaseToolTipGenerator(stdDevToolTipGenerator);
				
		tendChartPlot.setRangeAxis(1, stdDevAxis);
		tendChartPlot.setRangeAxisLocation(1, AxisLocation.TOP_OR_LEFT);
		tendChartPlot.setDataset(1, stdDevDataset);
		tendChartPlot.mapDatasetToRangeAxis(1, 1);
		tendChartPlot.setRenderer(1, stdDevRenderer);
		
		//New Pad
		XYLineAndShapeRenderer padRenderer = new XYLineAndShapeRenderer();
		padRenderer.setBaseShape(new Rectangle2D.Float(-2.0F, -2.0F, 4.0F, 4.0F));
		padRenderer.setBasePaint(Color.magenta);
		padRenderer.setSeriesPaint(0, Color.magenta);
		padRenderer.setUseFillPaint(true);
		padRenderer.setBaseFillPaint(Color.LIGHT_GRAY);
		padRenderer.setBaseShapesVisible(true);
		padRenderer.setBaseShapesFilled(true);
		CustomXYToolTipGenerator padToolTipGenerator = new CustomXYToolTipGenerator();
		padToolTipGenerator.addToolTipSeries(this.padToolTipArray);
		padRenderer.setBaseToolTipGenerator(padToolTipGenerator);
				
		tendChartPlot.setRangeAxis(2, newPadAxis);
		tendChartPlot.setRangeAxisLocation(2, AxisLocation.BOTTOM_OR_RIGHT);
		tendChartPlot.setDataset(2, newPadDataset);
		tendChartPlot.mapDatasetToRangeAxis(2, 2);
		tendChartPlot.setRenderer(2, padRenderer);
		
		// Add Horizontal Axis
		tendChartPlot.setDomainAxis(dateAxis);
	}
	
	/**
	 * Receive the data for plotting a new Tend Chart
	 * @param graphOption The WCS graph to be plotted: either TTV, TIR, STIR, Removal, or Taper SPC
	 * @param sList List of data for WCS graph data
	 * @param pList List of data for PadLife data
	 */
	public void loadData(int graphOption, String title, List<WCSDataInterface> sList, List<PadLife> pList)
	{
		averageDataset.removeAllSeries();
		stdDevDataset.removeAllSeries();
		newPadDataset.removeAllSeries();
		
		averageSeries.clear();
		stdDevSeries.clear();
		newPadSeries.clear();
		
		avgToolTipArray.clear();
		sdvToolTipArray.clear();
		padToolTipArray.clear();
		
		double average, stdDev, value1, value2, value3, value4;
		int index;
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:MM");
	
		for(WCSDataInterface sItem : sList)
		{
			value1 = sItem.getValue1();
			value2 = sItem.getValue2();
			value3 = sItem.getValue3();
			value4 = sItem.getValue4();
			
			average = (value1 + value2 + value3 + value4) /4;
			stdDev = java.lang.Math.sqrt( 
						(java.lang.Math.pow((value1 - average), 2) + 
						java.lang.Math.pow((value2 - average), 2) + 
						java.lang.Math.pow((value3 - average), 2) + 
						java.lang.Math.pow((value4 - average), 2) 
						) / 4
					);

			averageSeries.addOrUpdate(new Millisecond(sItem.getSpcStartDate()), average);
			index = averageSeries.getIndex(new Millisecond(sItem.getSpcStartDate()));
			avgToolTipArray.add(index, "Average=" + Constants.GRAPH_DF.format(average) + " @ " + sItem.getSpcStartDate() + ", Product=" + sItem.getProductID() + ", Block=" + sItem.getBlockID() + ", Pad Batch=" + sItem.getPadBatchNo());
		
			stdDevSeries.addOrUpdate(new Millisecond(sItem.getSpcStartDate()), stdDev);			
			index = stdDevSeries.getIndex(new Millisecond(sItem.getSpcStartDate()));
			sdvToolTipArray.add(index, "Std Dev=" + Constants.GRAPH_DF.format(stdDev) + " @ " + sItem.getSpcStartDate() + ", Product=" + sItem.getProductID() + ", Block=" + sItem.getBlockID() + ", Pad Batch=" + sItem.getPadBatchNo());
		}

		tendChart.setTitle(title);
		if(pList != null)
			for(PadLife pItem : pList)
			{
				long padStartTimeInMillis = pItem.getId().getStartLife().getTime();
				newPadSeries.addOrUpdate(new Millisecond(new Date(padStartTimeInMillis)), 0.0D);
				newPadSeries.addOrUpdate(new Millisecond(new Date(padStartTimeInMillis+1)), 1.0D);
				newPadSeries.addOrUpdate(new Millisecond(new Date(padStartTimeInMillis+2)), null);
	
				double padLifeHours = (pItem.getEndLife().getTime() - padStartTimeInMillis) / 3600000L; 
				padToolTipArray.add( Constants.GRAPH_DF.format(padLifeHours) + " Hours" + ", " + (pItem.getId().getStartLife()) + " to " + (pItem.getEndLife()));
				padToolTipArray.add( Constants.GRAPH_DF.format(padLifeHours) + " Hours" + ", " + (pItem.getId().getStartLife()) + " to " + (pItem.getEndLife()));
				padToolTipArray.add( Constants.GRAPH_DF.format(padLifeHours) + " Hours" + ", " + (pItem.getId().getStartLife()) + " to " + (pItem.getEndLife()));
			}
		
		averageDataset.addSeries(averageSeries);
		stdDevDataset.addSeries(stdDevSeries);
		newPadDataset.addSeries(newPadSeries);
		this.restoreAutoBounds();
		
	}
	
	public void drawChart(Graphics2D g2, Rectangle2D r2D)
	{
		tendChart.draw(g2, r2D);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void main(String [] args)
	{
		db.DatabaseManager dm = new db.DatabaseManager();
		DateFormat dtFmt = new java.text.SimpleDateFormat();
		
		List sList, pList;
		try {
			sList = dm.listSTIRByDCElement("5000-STIR_8A_6R", dtFmt.parse("08/02/2010 10:0 PM, PDT"), dtFmt.parse("08/16/2010 11:00 PM, PDT"));
			pList = dm.listPadlifeByStationNameDate("06", dtFmt.parse("08/02/2010 10:0 PM, PDT"), dtFmt.parse("08/16/2010 11:00 PM, PDT"));
			System.out.println("sList: "+sList.size());
			System.out.println("pList: "+sList.size());
			TendChartPanel tcPnl = new TendChartPanel();
			tcPnl.loadData(TendChartPanel.GRAPH_STIR, "A_6R", ((List<WCSDataInterface>)sList), (List<PadLife>)pList);
			javax.swing.JFrame window = new javax.swing.JFrame("Testing Graph");
			window.setLayout(new FlowLayout());
			window.getContentPane().add(tcPnl);
	        window.setSize(800, 500);
	        window.setLocation(50, 50);
			window.setVisible(true);
			
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
}
